package com.smartcommunity.elasticsearch.entranceguard;

import cn.hutool.core.util.NumberUtil;
import com.google.common.base.Joiner;
import com.smartcommunity.api.user.UserApi;
import com.smartcommunity.bean.enumeration.JudgeEnum;
import com.smartcommunity.bean.model.Pager;
import com.smartcommunity.bean.model.Result;
import com.smartcommunity.elasticsearch.entranceguard.req.EntranceGuardEsReq;
import com.smartcommunity.entity.ac.AccessDevice;
import com.smartcommunity.entity.entranceguard.AccessRecord;
import com.smartcommunity.entity.people.People;
import com.smartcommunity.es.common.EsIndex;
import com.smartcommunity.es.common.EsRestUtils;
import com.smartcommunity.service.access.AccessDeviceService;
import com.smartcommunity.service.people.PeopleService;
import com.smartcommunity.utils.ToolString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 门禁记录ESAPI
 */
@Component
@Slf4j
public class EntranceGuardEsApi {

    @Autowired
    private EsRestUtils eSRestUtils;

    @Autowired
    private UserApi userApi;

    @Autowired
    private PeopleService peopleService;

    @Autowired
    private AccessDeviceService accessDeviceService;

    public Pager<AccessRecord> getEntranceList(EntranceGuardEsReq entranceGuardEsReq) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        BoolQueryBuilder mustQueryBuilder = QueryBuilders.boolQuery();
        mustQueryBuilder.must(QueryBuilders.termsQuery("villageCode", entranceGuardEsReq.getVillageCode().split(",")));

        if (entranceGuardEsReq.getStartTime() != null) {
            mustQueryBuilder.must(QueryBuilders.rangeQuery("openTime").gte(entranceGuardEsReq.getStartTime()));
        }

        if (entranceGuardEsReq.getEndTime() != null) {
            mustQueryBuilder.must(QueryBuilders.rangeQuery("openTime").lte(entranceGuardEsReq.getEndTime()));
        }

        if (StringUtils.isNotBlank(entranceGuardEsReq.getDeviceId())) {
            mustQueryBuilder.must(QueryBuilders.matchPhraseQuery("deviceId", entranceGuardEsReq.getDeviceId()));
        }
        if (StringUtils.isNotBlank(entranceGuardEsReq.getBuildingNo())) {
            mustQueryBuilder.must(QueryBuilders.termQuery("buildingNo", entranceGuardEsReq.getBuildingNo()));
        }
        if (StringUtils.isNotBlank(entranceGuardEsReq.getHouseNo())) {
            mustQueryBuilder.must(QueryBuilders.termQuery("houseNo", entranceGuardEsReq.getHouseNo()));
        }
        if (StringUtils.isNotBlank(entranceGuardEsReq.getUnitNo())) {
            mustQueryBuilder.must(QueryBuilders.termQuery("unitNo", entranceGuardEsReq.getUnitNo()));
        }

        boolean should = false;
        if (StringUtils.isNotBlank(entranceGuardEsReq.getText())) {
            if (ToolString.isContainChinese(entranceGuardEsReq.getText())) {
                List<People> peoples = peopleService.getPeopleByName(entranceGuardEsReq.getText());
                if (CollectionUtils.isNotEmpty(peoples)) {
                    List<String> idCards = peoples.stream().map(People::getCredentialNo).collect(Collectors.toList());
                    mustQueryBuilder.must(QueryBuilders.termsQuery("credentialNo", idCards));
                } else {
                    return new Pager<>();
                }
            } else {
                queryBuilder
                        .should(QueryBuilders.boolQuery()
                                .must(QueryBuilders.wildcardQuery("cardNo", "*" + entranceGuardEsReq.getText() + "*"))
                                .must(mustQueryBuilder))
                        .should(QueryBuilders.boolQuery()
                                .must(QueryBuilders.wildcardQuery("credentialNo", "*" + entranceGuardEsReq.getText() + "*"))
                                .must(mustQueryBuilder));
                should = true;
            }
        }
        if (!should) {
            queryBuilder.must(mustQueryBuilder);
        }

        SortBuilder sortBuilder = eSRestUtils.builderSort(entranceGuardEsReq.getSortField(), entranceGuardEsReq.getSortMode());
        Pager<AccessRecord> pager = new Pager<>();
        try {
            String[] indexs;
            //如果条件中有开始时间
            if (entranceGuardEsReq.getStartTime() != null && entranceGuardEsReq.getEndTime() != null) {
                indexs = eSRestUtils.getIndexArray(entranceGuardEsReq.getStartTime(), entranceGuardEsReq.getEndTime(), EsIndex.ACCESSRECORD);
            } else {
                indexs = new String[]{EsIndex.ACCESSRECORD_ALIAS};
            }
            if (null == indexs) {
                return new Pager<>();
            }
            List<Map<String, Object>> list = eSRestUtils.page(indexs, queryBuilder, null, entranceGuardEsReq.getPageNum(), entranceGuardEsReq.getPageSize(), sortBuilder);
            if (list != null && list.size() > 0) {
                List<AccessRecord> entranceGuardList = mapToObj(list);
                int total = eSRestUtils.getTotalRecords(indexs, queryBuilder).intValue();
                return new Pager<>(entranceGuardEsReq.getPageNum(), entranceGuardEsReq.getPageSize(), total, entranceGuardList);
            }
        } catch (IOException e) {
            log.error("es  查询错误", e);
        }
        return pager;
    }

    public AccessRecord getLastAccessInfo(String deviceId) {
        AccessRecord ar = new AccessRecord();
        String nowDate;
        Date date = new Date();
        try {
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            if (deviceId != null) {
                boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("deviceId", deviceId));
            }
            SortBuilder sortBuilder = eSRestUtils.builderSort("openTime", "desc");
            nowDate = new SimpleDateFormat("yyyyMM").format(date);
            String[] indexs = new String[]{String.format(EsIndex.ACCESSRECORD, nowDate)};
            List<Map<String, Object>> list = eSRestUtils.page(indexs, boolQueryBuilder, null, 1, 10, sortBuilder);
            if (list != null && list.size() > 0) {
                List<AccessRecord> accessRecordList = mapToObj(list);
                ar = accessRecordList.get(0);
            }
        } catch (Exception e) {
            log.error("es  查询错误", e);
        }
        return ar;
    }

    private List<AccessRecord> mapToObj(List<Map<String, Object>> mapList) {
        List<AccessRecord> accessRecordList = new ArrayList<>();
        mapList.forEach(map -> {
            AccessRecord accessRecord = new AccessRecord();
            map.forEach((key, val) -> eSRestUtils.setFieldValueByFieldName(key, accessRecord, val));
            accessRecordList.add(accessRecord);
        });
        if (CollectionUtils.isNotEmpty(accessRecordList)) {
            List<String> credentialNos = accessRecordList.stream().filter(o -> StringUtils.isNotBlank(o.getCredentialNo())).map(AccessRecord::getCredentialNo).collect(Collectors.toList());
            List<String> deviceIds = accessRecordList.stream().filter(o -> StringUtils.isNotBlank(o.getDeviceId())).map(AccessRecord::getDeviceId).collect(Collectors.toList());
            List<People> peoples = null;
            List<AccessDevice> accessDevices = null;
            if (CollectionUtils.isNotEmpty(credentialNos)) {
                peoples = peopleService.getPeopleByCredentialNo(credentialNos);
            }
            if (CollectionUtils.isNotEmpty(deviceIds)) {
                accessDevices = accessDeviceService.getAccessDevice(deviceIds);
            }
            for (AccessRecord accessRecord : accessRecordList) {
                if (CollectionUtils.isNotEmpty(peoples)) {
                    for (People people : peoples) {
                        if (people.getCredentialNo().equals(accessRecord.getCredentialNo())) {
                            accessRecord.setName(people.getPeopleName());
                            accessRecord.setCredentialType(people.getCredentialType());
                            accessRecord.setSex(people.getGenderCode());
                            break;
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(accessDevices)) {
                    for (AccessDevice accessDevice : accessDevices) {
                        if (accessDevice.getDeviceId().equals(accessRecord.getDeviceId())) {
                            accessRecord.setDeviceName(accessDevice.getDeviceName());
                            accessRecord.setDeviceType(accessDevice.getDeviceType());
                            break;
                        }
                    }
                }
            }
        }
        return accessRecordList;
    }
}